package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.NameDuplicateException;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageBean;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.service.SetmealDishService;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealDetailVO;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 套餐业务接口实现类
 *
 * @Author Vsunks.v
 * @Date 2023/5/3 17:45
 * @Blog blog.sunxiaowei.net/996.mba
 * @Description: 套餐业务接口实现类
 */
@Service
public class SetmealServiceImpl implements SetmealService {

    @Autowired
    SetmealMapper setmealMapper;

    @Autowired
    SetmealDishService setmealDishService;

    @Autowired
    DishService dishService;

    /**
     * 带条件分页查询套餐（含分类名称）
     *
     * @param setmealPageQueryDTO 分页条件、查询条件
     * @return 符合条件的数据（含分类名称）
     */
    @Override
    public Result<PageBean> pageByCondition(SetmealPageQueryDTO setmealPageQueryDTO) {
        // 2. 使用分页助手插件设置分页参数
        PageHelper.startPage(setmealPageQueryDTO.getPage(), setmealPageQueryDTO.getPageSize());

        // 1. 按条件查询所有套餐（含分类名称）
        List<SetmealVO> setmeals = setmealMapper.selectByCondition(setmealPageQueryDTO);

        // 3. 获取分页相关数据
        Page<SetmealVO> page = (Page<SetmealVO>) setmeals;

        // 4. 组织数据并返回
        return Result.success(new PageBean(page.getTotal(), page.getResult()));
    }

    /**
     * 根据id查询套餐（含菜品）
     *
     * @param id 套餐id
     * @return 套餐（含菜品）
     */
    @Override
    public Result<SetmealVO> findByIdWithDishes(Long id) {
        // 调用mapper查询
        // 组装数据并返回
        SetmealVO object = setmealMapper.selectByIdWithDishes(id);
        return Result.success(object);
    }

    /**
     * 修改套餐（含菜品，按需更新）
     *
     * @param setmealDTO 套餐（含菜品）
     * @return
     */
    @Override
    @Transactional
    public Result updateByIdWithDishes(SetmealDTO setmealDTO) {

        // 1. 更新套餐基本信息
        // 1.1 准备数据
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);

        // 0. 查重
        if (isNameDuplcation(setmeal)) {
            throw new NameDuplicateException(setmeal.getName() + "重复，请修改后重试");
        }

        // 1.2 更新套餐
        if (setmealMapper.updateById(setmeal) > 0) {
            // 2. 更新菜品
            // 2.1 删除套餐详情（与对应菜品的关联关系）
            Long setmealId = setmeal.getId();
            setmealDishService.deleteBySetmealId(setmealId);
            // 2.2 获取并准备数据
            List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
            if (setmealDishes != null && setmealDishes.size() > 0) {
                // 2.3 完善菜品详情信息
                setmealDishes.forEach(sm -> sm.setSetmealId(setmealId));
                // 2.4 保存新的套餐详情（与对应菜品的关联关系）
                setmealDishService.saveBatch(setmealDishes);
            }
            return Result.success(MessageConstant.SETMEAL_UPDATE_SUCCESS);
        }
        return Result.error(MessageConstant.SETMEAL_UPDATE_FAILED);
    }

    /**
     * 启用停用套餐
     *
     * @param setmeal 套餐id和目标状态
     * @return 是否成功
     */
    @Override
    public Result switchStatus(Setmeal setmeal) {

        // 启售时：套餐包含的菜品中，如果存在停售菜品，则无法启售
        if (StatusConstant.ENABLE.equals(setmeal.getStatus())) {
            // 查询套餐下所有菜品
            List<Dish> dishes = dishService.findBySetmealId(setmeal.getId());
            // 遍历每个菜品，并判断其状态
            dishes.forEach(dish -> {
                // 如果存在停用的菜品，则本套餐禁止启用
                if (dish.getStatus().equals(StatusConstant.DISABLE)) {
                    throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED + ": " + dish.getName());
                }
            });
        }

        if (setmealMapper.updateStatusById(setmeal) > 0) {
            return Result.success(MessageConstant.SETMEAL_UPDATE_SUCCESS);
        }
        return Result.error(MessageConstant.SETMEAL_UPDATE_FAILED);
    }

    /**
     * 根据id批量删除套餐
     *
     * @param ids id们
     * @return 删除的结果
     */
    @Override
    public Result deleteByIds(List<Long> ids) {
        // 启用中套餐不能删除
        List<Setmeal> setmeals = setmealMapper.selectByIds(ids);

        setmeals.forEach(sm -> {
            if (sm.getStatus().equals(StatusConstant.ENABLE)) {
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        });

        // 删除套餐详情
        for (Long id : ids) {
            setmealDishService.deleteBySetmealId(id);
        }

        // 删除套餐
        for (Long id : ids) {
            setmealMapper.deleteById(id);
        }

        return Result.success(MessageConstant.SETMEAL_DELETE_SUCCESS);
    }

    /**
     * 新增套餐（含套餐详情<套餐和其包含菜品的关联关系>）
     *
     * @param setmealDTO 套餐+套餐详情
     * @return
     */
    @Override
    public Result saveWithSetmealDetails(SetmealDTO setmealDTO) {
        // 封装setmeal
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);

        // 姓名查重
        if (isNameDuplcation(setmeal)) {
            throw new NameDuplicateException(setmeal.getName() + "重复，请修改后再试！");
        }

        // 保存套餐基本信息
        setmeal.setStatus(StatusConstant.ENABLE);
        if (setmealMapper.insert(setmeal) > 0) {

            // 保存套餐详情
            List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
            if (setmealDishes != null && setmealDishes.size() > 0) {
                Long setmealId = setmeal.getId();
                setmealDishes.forEach(sm -> sm.setSetmealId(setmealId));
                setmealDishService.saveBatch(setmealDishes);
            }

            return Result.success(MessageConstant.SETMEAL_SAVE_SUCCESS);
        }
        return Result.error(MessageConstant.SETMEAL_SAVE_FAILED);
    }

    /**
     * 通用的查询名称是否重复。
     * 1. 添加、更新非状态字段时查重
     * 2. 更新状态字段不查重
     *
     * @param setmeal
     * @return
     */
    public boolean isNameDuplcation(Setmeal setmeal) {
        // 如果是修改状态，则不需要做重名判断
        if (setmeal.getName() == null) {
            return true;
        }
        // 查询并判断
        return setmealMapper.selectCountByName(setmeal) > 0;

    }

    /**
     * 动态条件查询套餐
     *
     * @param setmeal 条件
     * @return 符合条件的套餐
     */
    @Override
    public Result<List<Setmeal>> listByCondition(Setmeal setmeal) {
        // 调用mapper查询并返回
        return Result.success(setmealMapper.listByCondition(setmeal));
    }

    /**
     * 根据套餐id查询套餐详情
     *
     * @param setmealId 套餐id
     * @return 指定套餐的套餐详情
     */
    @Override
    public Result<List<SetmealDetailVO>> listSemealDetailsBySetmealId(Long setmealId) {
        // 调用mapper查询并返回
        return Result.success(setmealMapper.listSemealDetailsBySetmealId(setmealId));
    }
}
